package org.example.JVM.ByteCode.Util;


import com.sun.org.apache.bcel.internal.util.ClassLoader;
import org.example.JVM.ClassLoader.ByteCodeClassLoader;
import org.example.JVM.ClassLoader.ByteCodeHolder;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description:
 * @author: farprt
 * @create: 2022-11-16 21:56
 **/
public class ByteCodeUtils {

    public static void saveToFile(String className, byte[] byteCode) throws IOException {
        File file = new File("./src/main/" + className.replace(".", "/") + ".class");
        if ((!file.exists() || file.delete()) && file.createNewFile()) {
            try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
                fileOutputStream.write(byteCode);
            }
        }
    }

    public static Class<?> loadClass(String className,byte[] byteCode) throws IOException, ClassNotFoundException {
        saveToFile(className,byteCode);
        ByteCodeHolder byteCodeHolder=new ByteCodeHolder(byteCode);
        ByteCodeClassLoader byteCodeClassLoader=new ByteCodeClassLoader(new ClassLoader());
        return byteCodeClassLoader.findClass("src/main/" + className.replace(".", "/") + ".class");
    }


    public static String[] getParamDescriptors(String methodDescriptor) {
        List<String> paramDescriptors = new ArrayList<>();
        Matcher matcher = Pattern.compile("(L.*?;|\\[{0,2}L.*?;|[ZCBSIFJD]|\\[{0,2}[ZCBSIFJD]{1})")
                .matcher(methodDescriptor.substring(0, methodDescriptor.lastIndexOf(')') + 1));
        while (matcher.find()) {
            paramDescriptors.add(matcher.group(1));
        }
        if (paramDescriptors.size() == 0) {
            return null;
        }
        return paramDescriptors.toArray(new String[0]);
    }
}